---
title: Data Fetching
nav_title: Fetching
description: Learn best practices for fetching data on the server or client in Next.js.
---

Data fetching is a core part of any application. This page walks through best practices for fetching data using your preferred method.

## Should I fetch data on the server or the client?

Deciding whether to fetch data on the server or the client depends on the type of UI you're building.

For most cases, where you don't need real-time data (e.g. polling), you can fetch data on the server with [Server Components](/docs/app/building-your-application/rendering/server-components). There are a few benefits to doing this:

- You can fetch data in a single server-round trip, reducing the number of network requests and client-server waterfalls.
- Prevent sensitive information, such as access tokens and API keys, from being exposed to the client (which would require an intermediate API route).
- Reduce latency by fetching data close to the source (if your application code and database are in the same region).
- Data requests can be [cached](/docs/app/building-your-application/data-fetching/caching-and-revalidating#caching) and [revalidated](/docs/app/building-your-application/data-fetching/caching-and-revalidating#revalidating-data).

However, server-side data fetching will cause the whole page to be re-rendered on the server. In cases where you need to mutate/revalidate smaller pieces of UI or continually fetch real-time data (e.g. live views), client-side data fetching might be better suited, as it'll allow you to re-render the specific piece of UI on the client.

There are 4 ways you can fetch data in Next.js:

- [`fetch` API](#fetch-api) on the server.
- [ORMs or Database Clients](#orms-and-database-clients) on the server.
- [Route Handlers](#route-handlers) on the server, via the client.
- [Data Fetching Libraries](#data-fetching-libraries) on the client.

## `fetch` API

Next.js extends the native [`fetch` Web API](https://developer.mozilla.org/docs/Web/API/Fetch_API) `fetch` to allow you to configure the [caching](/docs/app/building-your-application/data-fetching/caching-and-revalidating#fetch-requests) and [revalidating](/docs/app/building-your-application/data-fetching/caching-and-revalidating#revalidating-data) behavior for each fetch request on the server. You can use `fetch` in [Server Components](/docs/app/building-your-application/rendering/server-components), [Route Handlers](/docs/app/building-your-application/routing/route-handlers), and [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations). For example:

```tsx filename="app/page.tsx" switcher
export default async function Page() {
  const data = await fetch('https://api.example.com/...').then((res) =>
    res.json()
  )

  return '...'
}
```

```jsx filename="app/page.js" switcher
export default async function Page() {
  const data = await fetch('https://api.example.com/...').then((res) =>
    res.json()
  )

  return '...'
}
```

By default, `fetch` requests retrieve fresh data. Using it will cause a whole route to be [dynamically rendered](/docs/app/building-your-application/rendering/server-components#dynamic-rendering) and data will not be cached.

You can cache `fetch` requests by setting the `cache` option to `force-cache`. This means data will be cached, and the component will be [statically rendered](/docs/app/building-your-application/rendering/server-components#static-rendering-default):

```js
fetch('https://...', { cache: 'force-cache' })
```

Alternatively, if using [PPR](/docs/app/building-your-application/rendering/partial-prerendering), we recommend wrapping components that use `fetch` requests in Suspense boundaries. This will ensure only the component that uses `fetch` is dynamically rendered and streamed in, rather than the entire page:

```tsx filename="@/app/ui/cart.tsx switcher
import { Suspense } from 'react'


export default async function Cart() {
  const res = await fetch('https://api.example.com/...')

  return '...'
}

export default function Navigation() {
  return (
    <>
      <Suspense fallback={<LoadingIcon />}>
        <Cart />
      </Suspense>
    <>
  )
}
```

See the [caching and revalidating](/docs/app/building-your-application/data-fetching/caching-and-revalidating) docs for more information.

> **Good to know:** In Next.js 14 and earlier, `fetch` requests were cached by default. See the [upgrade guide](/docs/app/building-your-application/upgrading/version-15) for more information.

### Request Memoization

If you need to fetch the same data in multiple components in a tree, you do not have to fetch data globally and pass props down. Instead, you can fetch data in the components that need the data without worrying about the performance implications of making multiple requests for the same data.

This is possible because `fetch` requests with the same URL and options are automatically memoized during a React render pass.

Learn more about [request memoization](/docs/app/building-your-application/caching#request-memoization).

## ORMs and Database Clients

You can call your ORM or database client in [Server Components](/docs/app/building-your-application/rendering/server-components), [Route Handlers](/docs/app/building-your-application/routing/route-handlers), and [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations).

You can use [React `cache`](https://react.dev/reference/react/cache) to memoize data requests during a React render pass. For example, although the `getItem` function is called in both layout and page, only one query will be made to the database:

```ts filename="app/utils.ts" switcher
import { cache } from 'react'

export const getItem = cache(async (id: string) => {
  const item = await db.item.findUnique({ id })
  return item
})
```

```js filename="app/utils.js" switcher
import { cache } from 'react'

export const getItem = cache(async (id) => {
  const item = await db.item.findUnique({ id })
  return item
})
```

```tsx filename="app/item/[id]/layout.tsx" switcher
import { getItem } from '@/utils/get-item'

export default async function Layout({
  params: { id },
}: {
  params: { id: string }
}) {
  const item = await getItem(id)
  // ...
}
```

```jsx filename="app/item/[id]/layout.js" switcher
import { getItem } from '@/utils/get-item'

export default async function Layout({ params: { id } }) {
  const item = await getItem(id)
  // ...
}
```

```tsx filename="app/item/[id]/page.tsx" switcher
import { getItem } from '@/utils/get-item'

export default async function Page({
  params: { id },
}: {
  params: { id: string }
}) {
  const item = await getItem(id)
  // ...
}
```

```jsx filename="app/item/[id]/page.js" switcher
import { getItem } from '@/utils/get-item'

export default async function Page({ params: { id } }) {
  const item = await getItem(id)
  // ...
}
```

You can also configure the caching and revalidating behavior of these requests using the experimental [`unstable_cache`](/docs/app/api-reference/functions/unstable_cache) and [`unstable_noStore`](/docs/app/api-reference/functions/unstable_noStore) APIs.

## Data Fetching Libraries

You can fetch data in Client Components using data fetching libraries such as [SWR](https://swr.vercel.app/) or [React Query](https://tanstack.com/query/latest). These libraries provide their own APIs for caching, revalidating, and mutating data.

For example, using SWR to fetch data periodically on the client:

```tsx filename="app/page.tsx switcher
"use client"

import useSWR from 'swr'
import fetcher from '@/utils/fetcher'

export default function PollingComponent {
  // Polling interval set to 2000 milliseconds
  const { data } = useSWR('/api/data', fetcher, { refreshInterval: 2000 });

  return '...'
}
```

```js filename="app/page.tsx" switcher
"use client"

import useSWR from 'swr'
import fetcher from '@/utils/fetcher'

export default function PollingComponent {
  // Polling interval set to 2000 milliseconds
  const { data } = useSWR('/api/data', fetcher, { refreshInterval: 2000 });

  return '...'
}
```

## Route Handlers

If you need to create API endpoints, Next.js supports [Route Handlers](/docs/app/building-your-application/routing/route-handlers). Route Handlers execute on the server and prevent sensitive information from being exposed to the client (e.g. API credentials).

For example, using SWR to call a Route Handler:

```tsx filename="app/ui/message.tsx" switcher
'use client'

import useSWR from 'swr'
import fetcher from '@/utils/fetcher'

export default function Message() {
  const { data } = useSWR('/api/messages', fetcher)

  return '...'
}
```

```jsx filename="app/ui/message.js" switcher
'use client'

import useSWR from 'swr'
import fetcher from '@/utils/fetcher'

export default function Message() {
  const { data } = useSWR('/api/messages', fetcher)

  return '...'
}
```

```tsx filename="app/api/messages/route.ts" switcher
export async function GET() {
  const data = await fetch('https://...', {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  }).then((res) => res.json())

  return Response.json({ data })
}
```

```js filename="app/api/messages/route.js" switcher
export async function GET() {
  const data = await fetch('https://...', {
    headers: {
      'Content-Type': 'application/json',
      'API-Key': process.env.DATA_API_KEY,
    },
  }).then((res) => res.json())

  return Response.json({ data })
}
```

See the [Route Handler](/docs/app/building-your-application/routing/route-handlers) docs for more examples.

> **Good to know**: Since Server Components render on the server, you don't need to call a Route Handler from a Server Component. You can access your data directly.

## Patterns

### Parallel and sequential data fetching

When fetching data inside components, you need to be aware of two data fetching patterns: Parallel and Sequential.

<Image
  alt="Sequential and Parallel Data Fetching"
  srcLight="/docs/light/sequential-parallel-data-fetching.png"
  srcDark="/docs/dark/sequential-parallel-data-fetching.png"
  width="1600"
  height="525"
/>

- **Sequential**: requests in a component tree are dependent on each other. This can lead to longer loading times.
- **Parallel**: requests in a route are eagerly initiated and will load data at the same time. This reduces the total time it takes to load data.

#### Sequential data fetching

If you have nested components, and each component fetches its own data, then data fetching will happen sequentially if those data requests are not [memoized](/docs/app/building-your-application/caching#request-memoization).

There may be cases where you want this pattern because one fetch depends on the result of the other. For example, the `Playlists` component will only start fetching data once the `Artist` component has finished fetching data because `Playlists` depends on the `artistID` prop:

```tsx filename="app/artist/[username]/page.tsx" switcher
export default async function Page({
  params: { username },
}: {
  params: { username: string }
}) {
  // Get artist information
  const artist = await getArtist(username)

  return (
    <>
      <h1>{artist.name}</h1>
      {/* Show fallback UI while the Playlists component is loading */}
      <Suspense fallback={<div>Loading...</div>}>
        {/* Pass the artist ID to the Playlists component */}
        <Playlists artistID={artist.id} />
      </Suspense>
    </>
  )
}

async function Playlists({ artistID }: { artistID: string }) {
  // Use the artist ID to fetch playlists
  const playlists = await getArtistPlaylists(artistID)

  return (
    <ul>
      {playlists.map((playlist) => (
        <li key={playlist.id}>{playlist.name}</li>
      ))}
    </ul>
  )
}
```

```jsx filename="app/artist/[username]/page.js" switcher
export default async function Page({ params: { username } }) {
  // Get artist information
  const artist = await getArtist(username)

  return (
    <>
      <h1>{artist.name}</h1>
      {/* Show fallback UI while the Playlists component is loading */}
      <Suspense fallback={<div>Loading...</div>}>
        {/* Pass the artist ID to the Playlists component */}
        <Playlists artistID={artist.id} />
      </Suspense>
    </>
  )
}

async function Playlists({ artistID }) {
  // Use the artist ID to fetch playlists
  const playlists = await getArtistPlaylists(artistID)

  return (
    <ul>
      {playlists.map((playlist) => (
        <li key={playlist.id}>{playlist.name}</li>
      ))}
    </ul>
  )
}
```

You can use [`loading.js`](/docs/app/building-your-application/routing/loading-ui-and-streaming) (for route segments) or [React `<Suspense>`](/docs/app/building-your-application/routing/loading-ui-and-streaming#streaming-with-suspense) (for nested components) to show an instant loading state while React streams in the result.

This will prevent the whole route from being blocked by data requests, and the user will be able to interact with the parts of the page that are ready.

#### Parallel Data Fetching

By default, layout and page segments are rendered in parallel. This means requests will be initiated in parallel.

However, due to the nature of `async`/`await`, an awaited request inside the same segment or component will block any requests below it.

To fetch data in parallel, you can eagerly initiate requests by defining them outside the components that use the data. This saves time by initiating both requests in parallel, however, the user won't see the rendered result until both promises are resolved.

In the example below, the `getArtist` and `getAlbums` functions are defined outside the `Page` component and initiated inside the component using `Promise.all`:

```tsx filename="app/artist/[username]/page.tsx" switcher
import Albums from './albums'

async function getArtist(username: string) {
  const res = await fetch(`https://api.example.com/artist/${username}`)
  return res.json()
}

async function getAlbums(username: string) {
  const res = await fetch(`https://api.example.com/artist/${username}/albums`)
  return res.json()
}

export default async function Page({
  params: { username },
}: {
  params: { username: string }
}) {
  const artistData = getArtist(username)
  const albumsData = getAlbums(username)

  // Initiate both requests in parallel
  const [artist, albums] = await Promise.all([artistData, albumsData])

  return (
    <>
      <h1>{artist.name}</h1>
      <Albums list={albums} />
    </>
  )
}
```

```jsx filename="app/artist/[username]/page.js" switcher
import Albums from './albums'

async function getArtist(username) {
  const res = await fetch(`https://api.example.com/artist/${username}`)
  return res.json()
}

async function getAlbums(username) {
  const res = await fetch(`https://api.example.com/artist/${username}/albums`)
  return res.json()
}

export default async function Page({ params: { username } }) {
  const artistData = getArtist(username)
  const albumsData = getAlbums(username)

  // Initiate both requests in parallel
  const [artist, albums] = await Promise.all([artistData, albumsData])

  return (
    <>
      <h1>{artist.name}</h1>
      <Albums list={albums} />
    </>
  )
}
```

In addition, you can add a [Suspense Boundary](/docs/app/building-your-application/routing/loading-ui-and-streaming) to break up the rendering work and show part of the result as soon as possible.

### Preloading Data

Another way to prevent waterfalls is to use the _preload_ pattern by creating an utility function that you eagerly call above blocking requests. For example, `checkIsAvailable()` blocks `<Item/>` from rendering, so you can call `preload()` before it to eagerly initiate `<Item/>` data dependencies. By the time `<Item/>` is rendered, its data has already been fetched.

Note that `preload` function doesn't block `checkIsAvailable()` from running.

```tsx filename="components/Item.tsx" switcher
import { getItem } from '@/utils/get-item'

export const preload = (id: string) => {
  // void evaluates the given expression and returns undefined
  // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/void
  void getItem(id)
}
export default async function Item({ id }: { id: string }) {
  const result = await getItem(id)
  // ...
}
```

```jsx filename="components/Item.js" switcher
import { getItem } from '@/utils/get-item'

export const preload = (id) => {
  // void evaluates the given expression and returns undefined
  // https://developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/void
  void getItem(id)
}
export default async function Item({ id }) {
  const result = await getItem(id)
  // ...
}
```

```tsx filename="app/item/[id]/page.tsx" switcher
import Item, { preload, checkIsAvailable } from '@/components/Item'

export default async function Page({
  params: { id },
}: {
  params: { id: string }
}) {
  // starting loading item data
  preload(id)
  // perform another asynchronous task
  const isAvailable = await checkIsAvailable()

  return isAvailable ? <Item id={id} /> : null
}
```

```jsx filename="app/item/[id]/page.js" switcher
import Item, { preload, checkIsAvailable } from '@/components/Item'

export default async function Page({ params: { id } }) {
  // starting loading item data
  preload(id)
  // perform another asynchronous task
  const isAvailable = await checkIsAvailable()

  return isAvailable ? <Item id={id} /> : null
}
```

> **Good to know:** The "preload" function can also have any name as it's a pattern, not an API.

#### Using React `cache` and `server-only` with the Preload Pattern

You can combine the `cache` function, the `preload` pattern, and the `server-only` package to create a data fetching utility that can be used throughout your app.

```ts filename="utils/get-item.ts" switcher
import { cache } from 'react'
import 'server-only'

export const preload = (id: string) => {
  void getItem(id)
}

export const getItem = cache(async (id: string) => {
  // ...
})
```

```js filename="utils/get-item.js" switcher
import { cache } from 'react'
import 'server-only'

export const preload = (id) => {
  void getItem(id)
}

export const getItem = cache(async (id) => {
  // ...
})
```

With this approach, you can eagerly fetch data, cache responses, and guarantee that this data fetching [only happens on the server](/docs/app/building-your-application/rendering/composition-patterns#keeping-server-only-code-out-of-the-client-environment).

The `utils/get-item` exports can be used by Layouts, Pages, or other components to give them control over when an item's data is fetched.

> **Good to know:**
>
> - We recommend using the [`server-only` package](/docs/app/building-your-application/rendering/composition-patterns#keeping-server-only-code-out-of-the-client-environment) to make sure server data fetching functions are never used on the client.

### Preventing sensitive data from being exposed to the client

We recommend using React's taint APIs, [`taintObjectReference`](https://react.dev/reference/react/experimental_taintObjectReference) and [`taintUniqueValue`](https://react.dev/reference/react/experimental_taintUniqueValue), to prevent whole object instances or sensitive values from being passed to the client.

To enable tainting in your application, set the Next.js Config `experimental.taint` option to `true`:

```js filename="next.config.js"
module.exports = {
  experimental: {
    taint: true,
  },
}
```

Then pass the object or value you want to taint to the `experimental_taintObjectReference` or `experimental_taintUniqueValue` functions:

```ts filename="app/utils.ts" switcher
import { queryDataFromDB } from './api'
import {
  experimental_taintObjectReference,
  experimental_taintUniqueValue,
} from 'react'

export async function getUserData() {
  const data = await queryDataFromDB()
  experimental_taintObjectReference(
    'Do not pass the whole user object to the client',
    data
  )
  experimental_taintUniqueValue(
    "Do not pass the user's address to the client",
    data,
    data.address
  )
  return data
}
```

```js filename="app/utils.js" switcher
import { queryDataFromDB } from './api'
import {
  experimental_taintObjectReference,
  experimental_taintUniqueValue,
} from 'react'

export async function getUserData() {
  const data = await queryDataFromDB()
  experimental_taintObjectReference(
    'Do not pass the whole user object to the client',
    data
  )
  experimental_taintUniqueValue(
    "Do not pass the user's address to the client",
    data,
    data.address
  )
  return data
}
```

```tsx filename="app/page.tsx" switcher
import { getUserData } from './data'

export async function Page() {
  const userData = getUserData()
  return (
    <ClientComponent
      user={userData} // this will cause an error because of taintObjectReference
      address={userData.address} // this will cause an error because of taintUniqueValue
    />
  )
}
```

```jsx filename="app/page.js" switcher
import { getUserData } from './data'

export async function Page() {
  const userData = await getUserData()
  return (
    <ClientComponent
      user={userData} // this will cause an error because of taintObjectReference
      address={userData.address} // this will cause an error because of taintUniqueValue
    />
  )
}
```
